﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Simple.Core;
using Simple.Core.Helper;

namespace Simple.EntityFrameworkCore
{
    public abstract class AppDbContext : DbContext
    {
        protected readonly string connectString;

        public AppDbContext(string connectString)
        {
            this.connectString = connectString;
        }

        public AppDbContext(DbContextOptions options) : base(options)
        {
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (ConfigHelper.GetValue<bool>("ShowEfCoreCommand"))
                optionsBuilder.UseLoggerFactory(new EFLoggerFactory());

            base.OnConfiguring(optionsBuilder);
        }

        /// <summary>
        /// 事务执行过程
        /// </summary>
        /// <param name="func"> </param>
        /// <returns> </returns>
        public (bool, Exception?) RunWithTran(Action<IDbContextTransaction> func)
        {
            var trans = Database.BeginTransaction();
            try
            {
                func.Invoke(trans);
                trans.Commit();
                return (true, null);
            }
            catch (Exception ex)
            {
                trans.Rollback();
                LogHelper.Error("事务执行出现异常", ex);
                return (false,ex);
            }
        }

        /// <summary>
        /// 根据SQL 执行后返回datatble
        /// </summary>
        /// <param name="sql">        </param>
        /// <param name="parameters"> </param>
        /// <returns> </returns>
        public DataTable GetTableFromSql(string sql, DbParameter[] parameters = null)
        {
            using (var conn = Database.GetDbConnection())
            {
                conn.ConnectionString = Database.GetConnectionString();
                conn.Open();
                var cmd = conn.CreateCommand();
                cmd.Connection = conn;
                cmd.CommandText = sql;
                if (parameters != null)
                {
                    foreach (var item in parameters)
                    {
                        cmd.Parameters.Add(item);
                    }
                }
                DataTable table = new DataTable("TempTable");
                using var reader = cmd.ExecuteReader();
                table.Load(reader);
                return table;
            }
        }

        public List<T> GetList<T>(string sql, DbParameter[] parameters = null)
        {
            var table = GetTableFromSql(sql, parameters);
            return JsonHelper.FromJson<List<T>>(table.Json());
        }
    }
}